package com.util;

import cn.hutool.core.util.HexUtil;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.util.Base64;

public class ThreeDes {

    // 算法名称
    public static final String KEY_ALGORITHM = "DESEDE";
    // 算法名称/加密模式/填充方式
    public static final String CIPHER_ALGORITHM = "DESEDE/ECB/NoPadding";


    private static SecretKey keyGenerator(String hexKeyStr) throws Exception {
        byte input[] = HexString2Bytes(hexKeyStr);
        for (int i=0;i<24;i++){
            byte[] tmpKey = new byte[24];
            System.arraycopy(input, 0, tmpKey, 0, 16);
            System.arraycopy(input, 0, tmpKey, 16, 8);
            input = tmpKey;
        }



        DESedeKeySpec keySpec = new DESedeKeySpec(input);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(keySpec);
        return secretKey;
    }

    private static int parse(char c) {
        if (c >= 'a') {
            return (c - 'a' + 10) & 0x0f;
        }
        if (c >= 'A') {
            return (c - 'A' + 10) & 0x0f;
        }
        return (c - '0') & 0x0f;
    }

    // 从十六进制字符串到字节数组转换
    public static byte[] HexString2Bytes(String hexstr) {
        byte[] b = new byte[hexstr.length() / 2];
        int j = 0;
        for (int i = 0; i < b.length; i++) {
            char c0 = hexstr.charAt(j++);
            char c1 = hexstr.charAt(j++);
            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
        }
        return b;
    }

    public static String encrypt(String data, String hexKeyStr) throws Exception {
        Key deskey = keyGenerator(hexKeyStr);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, deskey);
        byte[] results = cipher.doFinal(data.getBytes());
        return HexUtil.encodeHexStr(results);
    }

    public static String decrypt(String data, String hexKeyStr) throws Exception {
        Key deskey = keyGenerator(hexKeyStr);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, deskey);
        return new String(cipher.doFinal(HexUtil.decodeHex(data)));
    }



    /**
     * 加密方法
     *
     * @param src
     *            源数据的字节数组
     * @return
     */

    /**
     * @param encryptString
     *            需要加密的明文
     * @param encryptKey
     *            秘钥
     * @return 加密后的密文
     * @throws Exception
     */
    public static byte[] encryptDES(byte[] encryptString, byte[] encryptKey)
            throws Exception {
        // 实例化IvParameterSpec对象，使用指定的初始化向量
        // 实例化SecretKeySpec类，根据字节数组来构造SecretKey
        SecretKeySpec key = new SecretKeySpec(encryptKey, "DES/ECB/NoPadding");
        // 创建密码器
        Cipher cipher = Cipher.getInstance( "DES/ECB/NoPadding");
        // 用秘钥初始化Cipher对象
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 执行加密操作
        byte[] encryptedData = cipher.doFinal(encryptString);

        return encryptedData;//Base64.encodeToString(encryptedData, Base64.DEFAULT);
    }

    /**
     * 根据字符串生成密钥24位的字节数组
     *
     * @param keyStr
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] build3DesKey(String keyStr)
            throws UnsupportedEncodingException {
        byte[] key = new byte[24];
        byte[] temp = keyStr.getBytes("UTF-8");

        if (key.length > temp.length) {
            System.arraycopy(temp, 0, key, 0, temp.length);
        } else {
            System.arraycopy(temp, 0, key, 0, key.length);
        }
        return key;
    }

    public static void main(String[] args) throws Exception {
        String source = "22183F3500000000";
        System.out.println("原文: " + source);
        String key = "FFFFFFFFFFFFFFFF";
//        String encryptData1 = encrypt(source, key);
        String encryptData1 = new String(encryptDES(key.getBytes() , HexUtil.decodeHex(source))) ;
        System.out.println("加密后: 0082000008" + encryptData1);
        String dencryptData1 = decrypt(encryptData1,key);
        System.out.println("解密后: " + dencryptData1);
    }


}
